#include <linux/module.h>


#include "prot.h"
#include "exceptions.h"
#include "handlers.h"

#include "result_str.h"


void handlers(void);
void end_handlers(void);


#define info(...) printk("<1> info " __VA_ARGS__)



desc_ptr64 linux_idtr, test_idtr;
void *idt_page;

void init_constexts(void) {
	idt_page = (void *) get_zeroed_page (GFP_DMA);
	init_test_idt64(idt_page, (u64)handlers, 16);
	
	info ("h: %p\n", handlers);
	info ("eh: %p\n", end_handlers);
	
	
	test_idtr = make_test_idtr(idt_page);
	store_idt(&linux_idtr);
}

void test_idt_on(void) {
	load_idt(&test_idtr);
	memset(&INTERRUPTS.int_info, 0, sizeof(INTERRUPTS.int_info));
}



void test_idt_off(void) {
	load_idt(&linux_idtr);
}


void free_memory(void) {
	free_page((u64)idt_page);
}

asm("hmm:\n\t"
    "int $5\n\t"
);

int glob;
static int my_init(void)
{
  info("begin\n");
  init_constexts();
  
  print_header();
  
  
  /** Devide Error */
  test_idt_on();
  PREPARE_INTERRUPTS_HERE("DE");
  
  
  asm("xorl %ecx, %ecx\n\t"
      "divl %ecx\n\t");
  
  asm("DE:");
  test_idt_off();
  print_row ("DE", &INTERRUPTS.int_info);
  
  /** Global Protection error (clear LME)*/
  test_idt_on();
  PREPARE_INTERRUPTS_HERE("lmeGP");
  
  asm("movl $0xC0000080, %ecx\n\t"
      "rdmsr\n\t"
      "andl $(~(1<<8)), %eax\n\t"
      "wrmsr\n\t");
  
  asm("lmeGP:");
  test_idt_off();
  print_row ("lmeGP", &INTERRUPTS.int_info);
  
  /** int 14 */
  test_idt_on();
  PREPARE_INTERRUPTS_HERE("int14");
  
  asm("int $14");
  
  asm("int14:");
  test_idt_off();
  print_row ("int14", &INTERRUPTS.int_info);
  
  /** int 200 */
  test_idt_on();
  PREPARE_INTERRUPTS_HERE("int200");
  
  asm("int $200");
  
  asm("int200:");
  test_idt_off();
  print_row ("int200", &INTERRUPTS.int_info);
  
  /** mov from *1000 */
  test_idt_on();
  PREPARE_INTERRUPTS_HERE("mov1000");
  
  asm("movl 1000, %eax");
  
	asm("mov1000:");
  test_idt_off();
  print_row ("mov &1000", &INTERRUPTS.int_info);
	
	/** mov from *1000 */
	test_idt_on();
	PREPARE_INTERRUPTS_HERE("mov");
	
	asm("movl $1000, %eax");
	
	asm("mov:");
	test_idt_off();
	print_row ("mov", &INTERRUPTS.int_info);
  
  free_memory();
  info("finish\n");
  
  return 0;
}

static void my_exit(void) {
    info("exit\n");
}

module_init(my_init);
module_exit(my_exit);
